package controller

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"my_pro/model"
	"my_pro/schemas"
	"my_pro/utils"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

// 总路由分发
func UserRegister(userGrp *gin.RouterGroup) {
	userGrp.Use().POST("/userregister", userRegister)
	userGrp.Use().GET("/createcode", createcode)
	userGrp.Use().GET("/get_weibo", get_weibo)
	userGrp.Use().GET("/weiboCallback", weiboCallback)
	userGrp.Use().POST("/bindMobile", bindMobile)
	userGrp.Use().GET("/BdOCR", BdOCR)
	userGrp.Use().GET("/getHotPicture", getHotPicture)
	userGrp.Use().POST("/HotPictureUpload", HotPictureUpload)
	userGrp.Use().POST("/HotPictureData", HotPictureData)
	userGrp.Use().POST("/AddProclamation", AddProclamation)
	userGrp.Use().POST("/UserNumber", UserNumber)
	userGrp.Use().POST("/OpenBank", OpenBank)
	userGrp.Use().GET("/GetProclamation", GetProclamation)
	userGrp.Use().GET("/rollback", BankRollback)

}

func BankRollback(c *gin.Context) {
	id := c.Query("id")
	status := c.Query("status")
	sql := "update open_banks set status=? where id=?"
	err := model.DB.Exec(sql, status, id)
	fmt.Println(err, sql)
	if err.Error != nil {
		fmt.Println(err.Error)
		return
	}
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "审核完成",
	})
}

// 开户
func OpenBank(c *gin.Context) {
	var bank schemas.OpenBank
	_ = c.Bind(&bank)
	sql := "insert into Open_Banks(Name,Card_Number,Bank_Code,Mobile,Userid,card_url) values(?,?,?,?,?,'')"
	err := model.DB.Exec(sql, bank.Name, bank.CardNumber, bank.BankCode, bank.Mobile, bank.Userid)
	if err.Error != nil {
		fmt.Println(err.Error)
		return
	}
	var uid int
	sql1 := "select id from Open_Banks where userid=?"
	err2 := model.DB.Raw(sql1, bank.Userid).Scan(&uid)
	if err2.Error != nil {
		fmt.Println(err2.Error)
		return
	}
	r := utils.RedisPool
	r.ListAdd("openuser1", uid)
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "提交成功,等待审核",
	})
}

// 识别身份证
func UserNumber(c *gin.Context) {
	//	获取文件流
	f, err := c.FormFile("file")
	if err != nil {
		c.JSON(200, gin.H{
			"code": 10020,
			"msg":  "获取文件失败",
		})
		return
	}
	//// 生成文件
	imagepath := "images/" + f.Filename
	err2 := c.SaveUploadedFile(f, imagepath)
	if err2 != nil {
		fmt.Println(err2)
		c.JSON(200, gin.H{
			"code": 10021,
			"msg":  "保存文件失败",
		})
		return
	}
	c.JSON(200, gin.H{
		"code":  200,
		"image": imagepath,
	})

}

// 获取公告
func GetProclamation(c *gin.Context) {

	r := utils.RedisPool
	pro := r.Get("getProclamation")
	if pro != "" {
		fmt.Printf("上面")

		var aa interface{}
		json.Unmarshal([]byte(pro), &aa)
		proclamation := aa.([]interface{})

		c.JSON(200, gin.H{
			"code": 200,
			"msg":  "公告获取成功",
			"data": proclamation,
		})
	} else {

		flag := r.Setex("getproclamationuser", 100, "1")
		if flag {
			pro := model.Proclamation{}
			_ = c.Bind(pro)
			sql := "SELECT * from Proclamations order by id desc limit 0,5"
			var prodata []schemas.ProData
			model.DB.Raw(sql).Scan(&prodata)

			ulist, _ := json.Marshal(prodata)

			r.Setex("getProclamation", 1000, ulist)
			r.StrDel("getproclamationuser")

			c.JSON(200, gin.H{
				"code": 200,
				"msg":  "公告获取成功",
				"data": prodata,
			})
		}

	}

}

// 添加公告
func AddProclamation(c *gin.Context) {
	pro := schemas.Proclamation{}
	_ = c.Bind(pro)
	if pro.Content == "" {
		c.JSON(200, gin.H{
			"code": 10021,
			"msg":  "不能为空",
		})
		return
	}
	sql := "INSERT INTO Proclamation values (?)"
	model.DB.Exec(sql, pro.Content)
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "添加成功",
	})
}

// 获取热门图片
func getHotPicture(c *gin.Context) {
	r := utils.RedisPool
	hotp := r.Get("getpicture")
	if hotp != "" {
		fmt.Printf("上面")

		var aa interface{}
		json.Unmarshal([]byte(hotp), &aa)
		hotpicture := aa.([]interface{})

		c.JSON(200, gin.H{
			"code": 200,
			"msg":  "热门图片获取成功",
			"data": hotpicture,
		})
	} else {

		flag := r.Setex("getpictureuser", 100, "1")
		if flag {
			var hotpicture []schemas.HotPicture
			sql := "select * from hot_pictures order by id desc limit 0,3"
			model.DB.Raw(sql).Scan(&hotpicture)
			ulist, _ := json.Marshal(hotpicture)

			r.Setex("getpicture", 1000, ulist)
			r.StrDel("getpictureuser")

			c.JSON(200, gin.H{
				"code": 200,
				"msg":  "热门图片获取成功",
				"data": hotpicture,
			})
		}

	}

}

// 热门图片上传
func HotPictureUpload(c *gin.Context) {
	//	获取文件流
	f, err := c.FormFile("file")
	if err != nil {
		c.JSON(200, gin.H{
			"code": 10020,
			"msg":  "获取文件失败",
		})
		return
	}
	//// 生成文件
	imagepath := "images/hotpicture/" + f.Filename
	err2 := c.SaveUploadedFile(f, imagepath)
	if err2 != nil {
		fmt.Println(err2)
		c.JSON(200, gin.H{
			"code": 10021,
			"msg":  "保存文件失败",
		})
		return
	}
	sql := "INSERT INTO Hot_Pictures(Image_Path,go_url) values(?,'')"
	model.DB.Exec(sql, imagepath)
	var hid uint
	sql2 := "select id from Hot_Pictures where image_path=?"
	model.DB.Raw(sql2, imagepath).Scan(&hid)

	c.JSON(200, gin.H{
		"code": 10021,
		"msg":  "保存文件成功",
		"id":   hid,
	})

}

// 热门图片上传下一步
func HotPictureData(c *gin.Context) {
	picture := schemas.HotPicture{}
	_ = c.Bind(&picture)
	fmt.Println(picture)
	sql := "update Hot_Pictures set Go_url=?,sort=? where id=?"
	err3 := model.DB.Exec(sql, picture.Go_url, picture.Sort, picture.Id)
	fmt.Println(sql, err3)
	if err3.Error != nil {
		fmt.Println(err3.Error)
		return
	}
}

// 获取百度云接口
func GetAccToken() string {
	var host = "https://aip.baidubce.com/oauth/2.0/token"
	var param = map[string]string{
		"grant_type":    "client_credentials",
		"client_id":     "SI6aTBnhg3aAm5K6g14Ka9Ii",
		"client_secret": "SLNH64mAYrKLCR2CpvbUvLkEDVggCVjN",
	}

	uri, err := url.Parse(host)
	if err != nil {
		fmt.Println(err)
	}
	query := uri.Query()
	for k, v := range param {
		query.Set(k, v)
	}
	uri.RawQuery = query.Encode()

	response, err := http.Get(uri.String())
	if err != nil {
		fmt.Println(err)
	}
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println(err)
	}
	var v interface{}
	//把string转成接口
	json.Unmarshal([]byte(string(result)), &v)
	dictdata := v.(map[string]interface{})
	token := dictdata["access_token"].(string)

	return token

}

// 百度文字识别
func BdOCR(c *gin.Context) {
	imgpath := c.Query("imagepath")
	var host = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"
	var accessToken = GetAccToken()

	uri, err := url.Parse(host)
	if err != nil {
		fmt.Println(err)
	}
	query := uri.Query()
	query.Set("access_token", accessToken)
	uri.RawQuery = query.Encode()

	filebytes, err := ioutil.ReadFile(imgpath)
	if err != nil {
		fmt.Println(err)
	}

	image := base64.StdEncoding.EncodeToString(filebytes)
	sendBody := http.Request{}
	sendBody.ParseForm()
	sendBody.Form.Add("image", image)
	sendData := sendBody.Form.Encode()

	client := &http.Client{}
	request, err := http.NewRequest("POST", uri.String(), strings.NewReader(sendData))
	if err != nil {
		fmt.Println(err)
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	response, err := client.Do(request)
	defer response.Body.Close()
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(result))
	var v interface{}
	//把string转成接口
	json.Unmarshal([]byte(string(result)), &v)
	//
	mesdict := v.(map[string]interface{})
	//{'words_result':[["word":"张三"],["word":"171834795924857"]],'code':200,'time':123}
	fmt.Printf(">>>%T%v\n", mesdict["words_result"], mesdict["words_result"])
	wordslist := mesdict["words_result"].([]interface{})
	//
	var cardlist []string
	for _, vv := range wordslist {
		words := vv.(map[string]interface{})
		for _, vmes := range words {
			cardlist = append(cardlist, vmes.(string))
		}
	}

	c.JSON(200, gin.H{
		"code": "200",
		"name": cardlist[0],
		"card": cardlist[1],
	})
}

// 获取微博连接
func get_weibo(c *gin.Context) {
	//微博唯一标识
	clientid := "3674019597"
	//回调地址
	reurl := "http://127.0.0.1:8000/user/weiboCallback/"

	returnUrl := "https://api.weibo.com/oauth2/authorize?client_id=" + clientid + "&redirect_uri=" + reurl + "&response_type=code"
	fmt.Println(returnUrl)
	c.JSON(200, gin.H{
		"code": 200,
		"url":  returnUrl,
	})
}

// 微博回调
func weiboCallback(c *gin.Context) {
	//获取code
	code := c.Query("code")
	//组装数据post请求验证
	// data = {"client_id":'3674019597',"client_secret":"7ae99bc0d54ead29fc8d1b9fabd78587",
	// "grant_type":"authorization_code",
	// 'redirect_uri':'http://127.0.0.1:8000/user/weiboCallback/','code':code}
	geturl := "https://api.weibo.com/oauth2/access_token"
	data := url.Values{}
	data.Add("client_id", "3674019597")
	data.Add("client_secret", "7ae99bc0d54ead29fc8d1b9fabd78587")
	data.Add("grant_type", "authorization_code")
	data.Add("redirect_uri", "http://127.0.0.1:8000/user/weiboCallback/")
	data.Add("code", code)
	res, _ := http.PostForm(geturl, data)

	//成功 uid ,token

	body, _ := ioutil.ReadAll(res.Body)

	var v interface{}
	json.Unmarshal([]byte(string(body)), &v)

	resultmes := v.(map[string]interface{})

	actoken, flag := resultmes["access_token"]
	if flag {
		fmt.Println("actoken", actoken)
	}
	uid, uflag := resultmes["uid"]
	if uflag {
		fmt.Println("uid", uid)
	}

	//通过 uid去三方登录表中查询是否存在
	var sf_info model.SfLogin
	sql := "SELECT * from Sf_Logins where userid = ?"
	model.DB.Raw(sql, uid).Scan(&sf_info)
	fmt.Println(sf_info, "---------------------------------------")
	//如果存在用userid生成token，redirect到vue页面
	if sf_info.ID != 0 {
		token, _ := utils.ReleaseToken(sf_info.ID)

		c.Redirect(http.StatusMovedPermanently, "http://127.0.0.1:8080/?setToken="+token+"&userid="+strconv.Itoa(int(sf_info.ID)))
	} else {
		//如果不存在跳转到vue页面进行手机号的绑定

		c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/bindMobile?token="+fmt.Sprint(actoken)+"&userid="+fmt.Sprint(uid))
	}

}

// 绑定手机号
func bindMobile(c *gin.Context) {
	createUser := &schemas.CreateUser{}
	_ = c.Bind(createUser)
	token := createUser.Token
	uid := createUser.Uid
	mobile := createUser.Mobile

	//查询用户表中的此手机号是否存在
	var user schemas.Users
	sql := "select * from users where mobile=?"
	model.DB.Raw(sql, mobile).Scan(&user)

	//已经存在找出Userid,写入三方登录表
	var ctokenuserid uint = 0
	if user.Id != 0 {
		//生成token返回
		ctokenuserid = user.Id
	} else {
		//不存在先写用户表，生成一个userid，再写三方登录表
		sql2 := "insert into users(name,mobile,password) values (?,?,11)"
		err := model.DB.Exec(sql2, "游客"+mobile[len(mobile)-4:], mobile)
		if err.Error != nil {
			fmt.Println(err.Error)
			c.JSON(200, gin.H{
				"code": 400,
				"msg":  "错误",
			})
			return
		}
		var createUser model.User
		sql3 := "select * from users where mobile =?"
		model.DB.Raw(sql3, mobile).Scan(&createUser)
		ctokenuserid = createUser.ID
	}
	ctoken, _ := utils.ReleaseToken(ctokenuserid)
	//写入三方登录表
	sql4 := "insert into sf_logins(uid,token,plat_form,userid) values (?,?,?,?)"
	err := model.DB.Exec(sql4, ctokenuserid, token, "weibo", uid)
	if err.Error != nil {
		fmt.Println(err.Error)
		return
	}
	c.JSON(200, gin.H{
		"code":   200,
		"token":  ctoken,
		"userid": ctokenuserid,
	})
}

// 生成验证码
func createcode(c *gin.Context) {
	// 获取参数
	mobile := c.Query("mobile")
	//验证手机号格式是否合法
	reg := "^1[3-9]{1}\\d{9}$"
	result := regexp.MustCompile(reg)
	flag := result.MatchString(mobile)
	if !flag {
		c.JSON(200, gin.H{
			"code": "10011",
			"msg":  "手机号不正确",
		})
	} else {
		//	从redis中根据手机号获取验证码
		r := utils.GetRedis()
		value := r.Get(mobile)
		if value == "" {
			//	如果不存在生成随机数
			code := utils.RandInt(10000, 99999)
			//	调用发短信接口
			//strcode := strconv.Itoa(code)
			//utils.Sendsms(mobile, strcode)
			//	存入redis
			r.Setex(mobile, 60, code)
			//返回结果
			c.JSON(200, gin.H{
				"code": "200",
				"msg":  "发送成功",
				"sms":  code,
			})
		} else {
			c.JSON(200, gin.H{
				"code": "10012",
				"msg":  "不能重复发",
			})
		}
	}

}

// 注册
func userRegister(c *gin.Context) {
	user_info := schemas.Users{}
	_ = c.Bind(&user_info)

	if user_info.Mobile == "" || user_info.Code == "" {
		c.JSON(200, gin.H{
			"msg":  "不能为空",
			"code": "400",
		})
		return
	}
	r := utils.GetRedis()
	rcode := r.Get(user_info.Mobile)
	if rcode != user_info.Code {
		c.JSON(200, gin.H{
			"code": "10020",
			"msg":  "验证码不正确",
		})
	} else {
		//查询有没有当前用户
		var usermobile int
		sql5 := "select * from users where mobile =?"
		model.DB.Raw(sql5, user_info.Mobile).Scan(&usermobile)
		if usermobile != 0 {
			c.JSON(200, gin.H{
				"msg": "手机号已被注册",
			})
			return
		}
		var uname = "游客" + user_info.Mobile[len(user_info.Mobile)-4:]
		sql := "insert into users(name,mobile,password) values(?,?,'11')"

		err := model.DB.Exec(sql, uname, user_info.Mobile)
		if err != nil {
			fmt.Println(err.Error)
		}

		sql1 := "select id from users where mobile=?"
		var uid uint
		err2 := model.DB.Raw(sql1, user_info.Mobile).Scan(&uid)
		if err2 != nil {
			fmt.Println(err.Error)
		}

		token, _ := utils.ReleaseToken(uid)
		c.JSON(200, gin.H{
			"code":   "200",
			"msg":    "注册成功",
			"userid": uid,
			"token":  token,
		})
	}

}
